import React from "react";
import {
  NavBar,
  Icon,
  SearchBar,
  Popover,
  NoticeBar,
  Toast,
  Modal,
  Button,
} from "antd-mobile";
import "./style.less";
import Dialog from "@components/Dialog/Dialog";
import $ from "jquery";
import {
  keepLastIndex,
  getCursortPosition,
  setCaretPosition,
} from "@utils/Cursor";
import Recorder from "@utils/Recorder";
import { observer, inject } from "mobx-react";
import apis from "@apis/index";
import qs from "qs";

const Item = Popover.Item;
const alert = Modal.alert;

@inject("chatbot", "application")
@observer
class Home extends React.Component {
  autoFocusInst = null; // 搜索框ref
  inputDiv = null; // 输入框ref

  query = qs.parse(this.props.location.search.replace("?", ""));

  static defaultProps = {
    //设置props默认值方法
  };

  state = {
    chatbotInfo: {}, // 机器人信息
    appInfo: {}, // 应用信息
    searchBarVisible: false, //搜索栏是否显示
    popoverVisible: false, // 右上角弹出层是否显示
    popoverSelected: "", // 右上角弹出层已选中项目
    isConnected: true,
    isShowKeyBoard: true, // 是否是键盘模式
    isRecordAudio: false, // 是否录制语音中
    recordAudioObj: null, // 录制语音的对象
    operationType: "", // 上拉类型
    // emojiList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24],
    emojiList: [
      "😀",
      "😁",
      "😂",
      "😃",
      "😄",
      "😅",
      "😆",
      "😉",
      "😊",
      "😋",
      "😎",
      "😍",
      "😘",
      "😗",
      "😙",
      "😚",
      "😇",
      "😐",
      "😑",
      "😶",
      "😏",
      "😣",
      "😥",
      "😮",
      "😯",
      "😪",
      "😫",
      "😴",
      "😌",
      "😛",
      "😜",
      "😝",
      "😒",
      "😓",
      "😔",
      "😕",
      "😲",
      "😷",
      "😖",
      "😞",
      "😟",
      "😤",
      "😢",
      "😭",
      "😦",
      "😧",
      "😨",
      "😬",
      "😰",
      "😱",
      "😳",
      "😵",
      "😡",
      "😠",
      "💪",
      "👈",
      "👉",
      "👆",
      "👇",
      "✌",
      "✋",
      "👌",
      "👍",
      "👎",
      "✊",
      "👊",
      "👋",
      "👏",
      "👐",
      "❤️",
      "⭐",
      "🌟",
      "✨",
      "🎅",
    ],
    inputText: "", // 输入框富文本
    cursorPosition: null, // 光标位置
    atLeastRecordTime: 0.5, // 单位：秒
    // 对话列表
    conversationList: [],

    // 多媒体操作类型
    mediaOperationList: [
      {
        type: "image",
        icon: "fa-image",
        name: "图片",
      },
      {
        type: "photo",
        icon: "fa-camera-retro",
        name: "拍照",
      },
      {
        type: "audio",
        icon: "fa-microphone",
        name: "音频",
      },
      {
        type: "video",
        icon: "fa-video-camera",
        name: "视频",
      },
      {
        type: "file",
        icon: "fa-file-text-o",
        name: "文件",
      },
    ],
    webSocket: null, // 用于储存 socket.io 对象
    isShowHistoryList: false,
    localStorageHistoryListName: process.env.REACT_APP_LOCALSTORAGE_HISTORYLIST_NAME
  };

  async componentDidMount() {
    const { application } = this.props;
    let { appInfo } = this.query;

    // console.log("chatbotInfo", chatbotInfo)
    if (appInfo) {
      appInfo = JSON.parse(appInfo);
      appInfo.name = "Not Found";
      application.setInfo(appInfo);
    }else{
      return false
    }

    await this.getApplicationInfo();

    // 获取消息队列流
    this.setState(
      {
        webSocket: new WebSocket(
          `${process.env.REACT_APP_PRODUCTION_SOCKET_URL}/chatbot/privGroupSend/${appInfo.id}`
        ),
      },
      () => {
        this.updateConversationList({
          type: "text",
          name: "AI聊天机器人",
          position: "left",
          message: "AI聊天机器人正在连接...",
          time: new Date(),
        });

        const { webSocket, appInfo } = this.state;
        const applicationName = appInfo.name;

        // 连接 socket
        webSocket.onopen = () => {
          console.log("连接成功");
          this.setState({
            isConnected: true,
          });

          this.updateConversationList({
            type: "text",
            name: applicationName,
            position: "left",
            message: `连接成功。你好，我是属于「${applicationName}」应用的ChatBot机器人，请问有什么可以帮助到您。😊`,
            time: new Date(),
          });
        };

        // 用于指定收到服务器数据后的回调函数
        webSocket.onmessage = (data) => {
          console.log("接收成功", data);
          const item = JSON.parse(data.data);
          // console.log(item)
          if (item.type === "text") {
            this.updateConversationList({
              type: item.type,
              name: applicationName,
              position: "left",
              message: item.message,
              time: new Date(),
            });
          } else if(item.type === "template") {
            this.updateConversationList({
              type: item.type,
              name: applicationName,
              position: "left",
              template: item.template.body,
              time: item.time,
            });
          } else {
            this.updateConversationList({
              type: "text",
              name: applicationName,
              position: "left",
              message: "收到一条模板消息，暂不支持显示。",
              time: item.time,
            });
          }
        };

        //连接发生错误的回调方法
        webSocket.onerror = () => {};

        //连接关闭的回调方法
        webSocket.onclose = () => {};
      }
    );

    this.initRecordAudio();
  }

  bindKeyForChatBot = () => {
    const that = this;
    $("#input-rich-text").keypress(function ($event) {
      var keycode = window.event ? $event.keyCode : $event.which;
      var evt = $event || window.event;
      // var inputTxt = $(this);
      // 回车-->发送消息
      const inputRichText = that.state.inputText;
      if (keycode == 13 && !evt.ctrlKey) {
        // console.log("inputRichText", inputRichText)

        if (inputRichText) {
          // 发送消息的代码
          that.updateConversationList({
            type: "text",
            name: "测试用户",
            position: "right",
            message: inputRichText,
            time: new Date(),
          });

          that.sendMessage(inputRichText);
        } else {
          Toast.info("输入内容不能为空");
        }

        $event.preventDefault();
        return false;
      }
      // ctrl+回车-->换行
      if (evt.ctrlKey && evt.keyCode == 13) {
        // inputTxt.html(inputTxt.html() + '<br>');
        // that.inputDiv.focus()
        // keepLastIndex(that.inputDiv)
        $event.preventDefault();
        return false;
      }
    });
  };

  getApplicationInfo = () => {
    const { application } = this.props;
    const { info } = application;

    return apis.Home.getApplicationInfo(info.id).then((res) => {
      console.log("res", res);
      const data = res.data;
      this.setState({
        appInfo: data,
      });
      application.setInfo(data);
      this.forceUpdate();
    });
  };

  sendMessage = (msg, type = "text") => {
    const { application } = this.props;
    const { webSocket } = this.state;

    webSocket.send(msg);
  };

  goToBottom = () => {
    const ele = $("#conversation");
    let scrollHeight = ele[0].scrollHeight;
    ele.animate(
      {
        scrollTop: scrollHeight,
      },
      scrollHeight * 0.25 > 1.5 ? 1.5 : scrollHeight * 0.25
    );
  };

  initRecordAudio = () => {
    const recorde = Recorder();

    this.setState({
      recordAudioObj: recorde,
    });
  };

  updateConversationList = (info) => {
    const { conversationList, localStorageHistoryListName, appInfo } = this.state;

    conversationList.push(info);

    // 对话历史记录
    let list = localStorage.getItem(
      `${appInfo.id}-${localStorageHistoryListName}`
    );
    list = list ? JSON.parse(list) : []
    list.push(info)

    localStorage.setItem(
      `${appInfo.id}-${localStorageHistoryListName}`,
      JSON.stringify(list)
    );

    this.setState(
      {
        conversationList,
        inputText: "",
      },
      () => {
        if (this.inputDiv) {
          this.inputDiv.innerText = "";
        }
        this.goToBottom();
      }
    );
  };

  render() {
    const {
      searchBarVisible,
      popoverVisible,
      popoverSelected,
      conversationList,
      isConnected,
      isShowKeyBoard,
      inputText,
      emojiList,
      mediaOperationList,
      isRecordAudio,
      recordAudioObj,
      atLeastRecordTime,
      operationType,
      isShowHistoryList,
      localStorageHistoryListName,
      appInfo
    } = this.state;
    const { location, history, chatbot, application } = this.props;
    const { pathname } = location;

    return (
      <div className="home">
        {!searchBarVisible ? (
          <NavBar
            mode="light"
            rightContent={[
              // <Icon
              //   key="0"
              //   type="search"
              //   style={{ marginRight: "16px" }}
              //   onClick={() => {
              //     this.setState(
              //       {
              //         searchBarVisible: true,
              //       },
              //       () => {
              //         this.autoFocusInst?.focus();
              //       }
              //     );
              //   }}
              // />,
              <Popover
                overlayClassName="fortest"
                overlayStyle={{ color: "currentColor" }}
                visible={popoverVisible}
                overlay={[
                  <Item
                    key="5"
                    value={`/qrcode`}
                    icon={<i class="fa fa-qrcode fa-lg"></i>}
                    style={{ whiteSpace: "nowrap" }}
                  >
                    在手机上使用
                  </Item>,
                  <Item
                    key="5"
                    value={"/settings"}
                    icon={<i class="fa fa-cog fa-lg"></i>}
                    style={{ whiteSpace: "nowrap" }}
                  >
                    设置
                  </Item>,
                  <Item
                    key="6"
                    value={"/about"}
                    icon={<i class="fa fa-info-circle fa-lg"></i>}
                  >
                    <span style={{ marginRight: 5 }}>关于</span>
                  </Item>,
                ]}
                align={{
                  overflow: { adjustY: 0, adjustX: 0 },
                  offset: [-10, 0],
                }}
                onVisibleChange={(visible) => {
                  this.setState({
                    popoverVisible: visible,
                  });
                }}
                onSelect={(opt) => {
                  let url = opt.props.value;

                  this.setState(
                    {
                      popoverVisible: false,
                      popoverSelected: opt.props.value,
                    },
                    () => {
                      history.push(url);
                    }
                  );
                }}
              >
                <div
                  style={{
                    height: "100%",
                    padding: "0 15px",
                    marginRight: "-15px",
                    display: "flex",
                    alignItems: "center",
                  }}
                >
                  <Icon type="ellipsis" />
                </div>
              </Popover>,
            ]}
          >
            {application.info.name}
          </NavBar>
        ) : (
          <SearchBar
            onBlur={() => {
              this.setState({
                searchBarVisible: false,
              });
            }}
            onCancel={() => {
              this.setState({
                searchBarVisible: false,
              });
            }}
            placeholder="请输入机器人名称..."
            ref={(ref) => (this.autoFocusInst = ref)}
          />
        )}

        <NoticeBar
          className={`notice-bar is-show-notice-bar-${!isConnected}`}
          action={
            <span
              onClick={() => {
                Toast.info("正在重新连接中...", 2);
                this.connectChatBot();
              }}
            >
              重新连接
            </span>
          }
          icon={<i class="fa fa-chain-broken"></i>}
          mode="link"
        >
          无法连接到服务器，请检查网络设置...
        </NoticeBar>

        <div
          id="conversation"
          onFocus={() => {
            this.setState({
              operationType: "",
            });
          }}
          tabindex="-1"
          className="conversation"
        >
          {!isShowHistoryList ? (
            <div className="showHistory" onClick={() => {
              let list = localStorage.getItem(`${appInfo.id}-${localStorageHistoryListName}`)
              list = list ? JSON.parse(list) : []

              if(list.length > 0) this.setState({
                conversationList: list
              }, () => {
                this.goToBottom()
              })

              this.setState({
                isShowHistoryList: true
              })
            }}>查看历史记录</div>
          ) : null}

          {conversationList.map((item, index) => {
            return (
              <Dialog
                type={item.type}
                url={item.url}
                name={item.name}
                position={item.position}
                message={item.message}
                time={item.time}
                template={item.template}
              ></Dialog>
            );
          })}
        </div>

        <div className="operation">
          <div className="operation-bar">
            {isShowKeyBoard ? (
              <div
                className="item"
                onClick={() => {
                  this.setState({
                    isShowKeyBoard: false,
                    operationType: "",
                  });
                }}
              >
                <i class="fa fa-keyboard-o fa-2x"></i>
              </div>
            ) : (
              <div
                className="item"
                onClick={() => {
                  if (isRecordAudio) {
                    Toast.info("录音完成", 1, () => {
                      Toast.hide();
                    });
                    this.setState({
                      isRecordAudio: false,
                    });
                  }
                  this.setState(
                    {
                      isShowKeyBoard: true,
                    },
                    () => {
                      this.inputDiv.focus();
                      keepLastIndex(this.inputDiv);
                    }
                  );
                }}
              >
                <i class="fa fa-microphone fa-2x"></i>
              </div>
            )}

            <div className="user-input">
              {isShowKeyBoard ? (
                <div
                  id="input-rich-text"
                  ref={(inputDiv) => {
                    this.inputDiv = inputDiv;
                  }}
                  style={{ height: "auto" }}
                  onKeyUp={(e) => {
                    this.setState({
                      inputText: this.inputDiv.innerText,
                    });
                  }}
                  onFocus={() => {
                    this.bindKeyForChatBot();
                  }}
                  onBlur={() => {
                    let position = getCursortPosition($("#input-rich-text")[0]);
                    // console.log(position)
                    this.setState({
                      cursorPosition: position,
                    });
                    $("#input-rich-text").unbind();
                  }}
                  className="input-content"
                  contentEditable="true"
                  placeholder="你想说什么..."
                ></div>
              ) : !isRecordAudio ? (
                <div
                  className="record-audio"
                  onClick={() => {
                    this.setState(
                      {
                        isRecordAudio: true,
                      },
                      () => {
                        recordAudioObj
                          .open(function () {
                            recordAudioObj.start();
                          })
                          .catch((err) => {
                            if (err) {
                              console.log(err);
                              if (!err.isUserNotAllow) {
                                Toast.info(<div>已停止录音</div>, 2);
                              } else {
                                Toast.info(
                                  <div>
                                    没有麦克风使用权限，
                                    <br />
                                    无法录音
                                  </div>,
                                  2
                                );
                              }

                              this.setState({
                                isRecordAudio: false,
                              });
                            }
                          });

                        Toast.info(
                          <div className="custom-toast">
                            <div className="icon">
                              <i class="fa fa-microphone fa-2x"></i>
                            </div>
                            <div className="content">正在录音</div>
                          </div>,
                          0,
                          null,
                          false
                        );
                      }
                    );
                  }}
                >
                  点击开始说话
                </div>
              ) : (
                <div
                  className="record-audio"
                  onClick={async () => {
                    const audioInfo = await recordAudioObj
                      .stop()
                      .then((res) => {
                        return res;
                      });
                    // console.log(audioInfo)

                    if (
                      audioInfo &&
                      audioInfo.duration &&
                      audioInfo.duration >= atLeastRecordTime * 1000
                    ) {
                      let that = this;
                      alert(
                        "是否发送该语音",
                        <audio
                          className="pre-audio"
                          src={audioInfo.blobUrl}
                          controls={true}
                        ></audio>,
                        [
                          {
                            text: "取消",
                            onPress: (value) =>
                              new Promise((resolve) => {
                                resolve();
                              }),
                          },
                          {
                            text: "发送",
                            onPress: (value) =>
                              new Promise((resolve, reject) => {
                                this.updateConversationList({
                                  type: "audio",
                                  name: "测试用户",
                                  position: "right",
                                  url: audioInfo.blobUrl,
                                  time: new Date(),
                                });

                                // this.sendMessage(inputText)

                                resolve();
                              }),
                          },
                        ]
                      );

                      Toast.info("录音完成", 1, () => {
                        Toast.hide();
                      });
                    } else {
                      Toast.info("语音太短，已取消", 1);
                    }
                    this.setState({
                      isRecordAudio: false,
                    });
                  }}
                >
                  点击停止录音
                </div>
              )}
            </div>
            <div
              id="emoji"
              className="item"
              onClick={() => {
                this.setState(
                  {
                    operationType: "emoji",
                    isShowKeyBoard: true,
                  },
                  () => {
                    this.inputDiv.focus();
                    keepLastIndex(this.inputDiv);
                    this.goToBottom();
                  }
                );
              }}
            >
              <i class="fa fa-smile-o fa-2x"></i>
            </div>
            <div
              className="item"
              onClick={() => {
                this.setState(
                  {
                    operationType: "media",
                    // isShowKeyBoard: true
                  },
                  () => {
                    this.goToBottom();
                  }
                );
              }}
            >
              <i class="fa fa-plus-circle fa-2x"></i>
            </div>

            <div
              className={`item send send-${inputText && isShowKeyBoard}`}
              onClick={() => {
                this.updateConversationList({
                  type: "text",
                  name: "测试用户",
                  position: "right",
                  message: inputText,
                  time: new Date(),
                });
                this.sendMessage(inputText);
                this.inputDiv.focus();
              }}
            >
              <i class="fa fa-arrow-circle-up fa-2x"></i>
            </div>
          </div>

          <div
            className="operation-info"
            style={{ paddingTop: operationType !== "" ? "5px" : "0" }}
          >
            <div
              className="emoji-picker-list-3"
              style={{
                height: operationType === "emoji" ? "128px" : "0",
                paddingBottom: operationType === "emoji" ? "10px" : "0",
              }}
            >
              {emojiList.map((item, index) => {
                return (
                  <div
                    className="emoji-item"
                    onClick={() => {
                      const { cursorPosition: position } = this.state;
                      this.inputDiv.focus();

                      let prefix = this.inputDiv.innerText.slice(0, position);
                      let suffix = this.inputDiv.innerText.slice(position);
                      this.inputDiv.innerText = prefix + item + suffix;
                      let afterPosition = position + item.length;
                      this.setState({
                        cursorPosition: afterPosition,
                      });
                      setCaretPosition($("#input-rich-text")[0], afterPosition);

                      this.setState({
                        inputText: this.inputDiv.innerText,
                      });
                    }}
                    key={index}
                    data-index={index}
                  >
                    {item}
                  </div>
                );
              })}
            </div>

            <div
              className="media-operation-list"
              style={{ height: operationType === "media" ? "128px" : "0" }}
            >
              {mediaOperationList.map((item, index) => {
                return (
                  <div className="item">
                    <div className="icon">
                      <i class={`fa ${item.icon}`}></i>
                    </div>
                    <div className="name">{item.name}</div>
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default Home;
